package org.extframework.ld.http.abstr;

import java.io.IOException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.extframework.ld.conf.ParameterNames;
import org.extframework.ld.http.EncryptionWebRequest;
import org.extframework.ld.http.EncryptionWebResponse;
import org.extframework.ld.util.ExtMessage;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * @author : Dong.Li
 * @created : 2013-1-17
 * @version : 1.0
 * @description :
 */
public abstract class AbstractEncryptionWebServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	/**
	 * 只允许ajax访问
	 */
	protected boolean ajaxRequest = true;
	/**
	 * 系统错误消息是否以json形式返回
	 * false 把错误消息设置在request容器中 key:errorSystemMsg
	 */
	protected boolean errorJsonMsg = true;
	private ApplicationContext applicationContext;
	protected final transient Log logger = LogFactory.getLog(super.getClass());

	protected final void service(HttpServletRequest req,
			HttpServletResponse resp) throws ServletException, IOException {
		String action = req.getParameter(ParameterNames.WEB_ACTION_MARK);

		AbstractEncryptionWebRequest request = new EncryptionWebRequest(req);
		AbstractEncryptionWebResponse response = new EncryptionWebResponse(resp);
		response.setCharacterEncoding("utf-8");

		initParmeter(request, response);

		if ((this.ajaxRequest) && (!(isAjaxRequested(req)))) {
			response.setContentType("text/json; charset=UTF-8");
			response.printStr("不正确的请求方式!");
			return;
		}
		action = action==null?"index":action;
		action = ((action != null) && (action.equals("init"))) ? "index"
				: action;
		try {
			Method method = super.getClass().getDeclaredMethod(
					action,
					new Class[] { AbstractEncryptionWebRequest.class,
							AbstractEncryptionWebResponse.class });
			method.invoke(this, new Object[] { request, response });
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			
			if(!isAjaxRequested(req)){//如果不是ajax请求
				response.sendError(404);
				return;
			}
			
			logger.error("NoSuchMethodException", e);
			if(errorJsonMsg){
				response.setContentType("text/json; charset=UTF-8");
				response.printJson(ExtMessage.showErrorMessage(e.getMessage()));
			}else{
				req.getSession(true).setAttribute("errorSystemMsg", e.getMessage());
			}
		} catch (Exception e) {
			e.printStackTrace();
			
			if(!isAjaxRequested(req)){//如果不是ajax请求
				response.sendError(500);
				return;
			}
			
			logger.error("Exception", e);
			if(errorJsonMsg){
				response.setContentType("text/json; charset=UTF-8");
				response.printError(ExtMessage.showErrorMessage(e.getMessage()));
			}else{
				req.getSession(true).setAttribute("errorSystemMsg", e.getMessage());
			}
		}
	}

	private void initParmeter(AbstractEncryptionWebRequest req,
			AbstractEncryptionWebResponse resp) throws ServletException,
			IOException {
		if (this.applicationContext == null) {
			this.applicationContext = WebApplicationContextUtils
					.getWebApplicationContext(getServletContext());
		}
		init(req, resp);
	}

	protected abstract void init(
			AbstractEncryptionWebRequest paramAbstractEncryptionWebRequest,
			AbstractEncryptionWebResponse paramAbstractEncryptionWebResponse)
			throws ServletException, IOException;

	public abstract void index(AbstractEncryptionWebRequest paramHttpServletRequest,
			AbstractEncryptionWebResponse paramHttpServletResponse)
			throws ServletException, IOException;

	private final boolean isAjaxRequested(HttpServletRequest req) {
		String requestType = req.getHeader("X-Requested-With");

		return (requestType != null);
	}

	protected <T> T getBean(Class<T> paramClass) {
		return this.applicationContext.getBean(paramClass);
	}

	protected Object getBean(String beanId) {
		return this.applicationContext.getBean(beanId);
	}

}
